package com.ruoyi.framework.shiro.util.secret;

import com.ruoyi.framework.shiro.realm.ThirdRealm;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * AES加密解密
 *
 * @author wd
 */
public class SecurityUtil {
    private static final Logger log = LoggerFactory.getLogger(ThirdRealm.class);

    private SecurityUtil() {
    }

    /**
     * AES加密
     *
     * @param content 明文
     * @return 密文
     */
    public static String encryptAES(String content, String secretKey) {
        if (!checkParam(content, secretKey)) {
            return null;
        }
        //AES加密
        return encrypt(content, secretKey);
    }

    /**
     * AES解密
     *
     * @param encryptResultStr 密文
     * @return 明文
     */
    public static String decryptAES(String encryptResultStr, String secretKey) {
        if (!checkParam(encryptResultStr, secretKey)) {
            return null;
        }
        try {
            // BASE64位解密
            byte[] decryptFrom = Base64.getDecoder().decode(encryptResultStr);

            //AES解密
            byte[] decryptResult = decrypt(decryptFrom, secretKey);
            return new String(decryptResult);
        } catch (Exception e) {
            log.error("解密失败", e);
            // 当密文不规范时会报错，可忽略，但调用的地方需要考虑
            return null;
        }
    }

    /**
     * 校验参数
     */
    private static boolean checkParam(String encryptResultStr, String secretKey) {
        if (StringUtils.isBlank(encryptResultStr)) {
            log.error("校验失败，{}", "主体内容为空");
            return false;
        }
        if (!secretKey.matches("^[a-z0-9A-Z]+$")) {
            log.error("校验失败，{}", "密钥格式错误");
            return false;
        }

        return true;
    }


    /**
     * 加密
     *
     * @param content 需要加密的内容
     * @param secretKey  加密密钥
     * @return
     */
    private static String encrypt(String content, String secretKey) {
        try {
            byte[] raw = secretKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, keySpec);
            byte[] bytes = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(bytes);
        } catch (Exception e) {
            log.error("加密失败", e);
            return null;
        }
    }

    /**
     * 解密
     *
     * @param content 待解密内容
     * @param secretKey  解密密钥
     * @return
     */
    private static byte[] decrypt(byte[] content, String secretKey) {
        try {
            byte[] raw = secretKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//NOSONAR  sonar扫描忽略这段代码
            cipher.init(Cipher.DECRYPT_MODE, keySpec);
            return cipher.doFinal(content);
        } catch (Exception e) {
            log.error("解密失败", e);
            return null;
        }
    }
}
